home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1996 May: Tool Chest / Developer CD Series May 1996 (Tool Chest) (Apple Computer) (1996).iso / Tool Chest / Development Tools & Languages / Dylan Related / Mindy / Mindy 1.2 - portable sources / comp / envanal.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-03-15  |  11.7 KB  |  445 lines  |  [TEXT/ttxt]

  1. /**********************************************************************\
  2. *
  3. *  Copyright (c) 1994  Carnegie Mellon University
  4. *  All rights reserved.
  5. *  
  6. *  Use and copying of this software and preparation of derivative
  7. *  works based on this software are permitted, including commercial
  8. *  use, provided that the following conditions are observed:
  9. *  
  10. *  1. This copyright notice must be retained in full on any copies
  11. *     and on appropriate parts of any derivative works.
  12. *  2. Documentation (paper or online) accompanying any system that
  13. *     incorporates this software, or any part of it, must acknowledge
  14. *     the contribution of the Gwydion Project at Carnegie Mellon
  15. *     University.
  16. *  
  17. *  This software is made available "as is".  Neither the authors nor
  18. *  Carnegie Mellon University make any warranty about the software,
  19. *  its performance, or its conformity to any specification.
  20. *  
  21. *  Bug reports, questions, comments, and suggestions should be sent by
  22. *  E-mail to the Internet address "gwydion-bugs@cs.cmu.edu".
  23. *
  24. ***********************************************************************
  25. *
  26. * $Header: envanal.c,v 1.11 94/10/05 20:54:39 nkramer Exp $
  27. *
  28. * This file performs environment analysis.
  29. *
  30. \**********************************************************************/
  31.  
  32. #include "../compat/std-c.h"
  33.  
  34. #include "mindycomp.h"
  35. #include "src.h"
  36. #include "lexenv.h"
  37. #include "envanal.h"
  38. #include "sym.h"
  39. #include "lose.h"
  40.  
  41. static void analize_expr(struct expr *expr, struct lexenv *lexenv);
  42. static void analize_body(struct body *body, struct lexenv *lexenv);
  43.  
  44.  
  45. /* Utilities */
  46.  
  47. static struct binding
  48.     *find_and_maybe_close_over(struct id *id, struct lexenv *lexenv,
  49.                    struct closes_over **over_ptr)
  50. {
  51.     struct method *method = lexenv->method;
  52.     struct binding *binding;
  53.     struct closes_over *over;
  54.  
  55.     for (binding = lexenv->bindings; binding != NULL; binding = binding->next)
  56.     if (binding->id->symbol == id->symbol
  57.         && binding->id->internal == id->internal)
  58.         break;
  59.  
  60.     if (binding == NULL)
  61.     return NULL;
  62.  
  63.     if (binding->home != method) {
  64.     /* It is a closure var. */
  65.     binding->closed_over = TRUE;
  66.  
  67.     do {
  68.         for (over = method->closes_over; over != NULL; over = over->next)
  69.         if (over->binding == binding) {
  70.             /* We already know that this method closes over this */
  71.             /* binding.  */
  72.             *over_ptr = over;
  73.             return binding;
  74.         }
  75.  
  76.         over = malloc(sizeof(struct closes_over));
  77.         over->binding = binding;
  78.         over->over = NULL;
  79.         over->offset = method->lexenv_size++;
  80.         over->next = method->closes_over;
  81.         method->closes_over = over;
  82.         method->nargs++;
  83.  
  84.         *over_ptr = over;
  85.         over_ptr = &over->over;
  86.  
  87.         method = method->parent;
  88.     } while (method != binding->home);
  89.     *over_ptr = NULL;
  90.     return binding;
  91.     }
  92.     else
  93.     return binding;
  94. }
  95.  
  96. static void analize_method(struct method *method, struct lexenv *lexenv)
  97. {
  98.     struct method *parent = lexenv->method;
  99.     struct binding *bindings = lexenv->bindings;
  100.     int offset = 0;
  101.     struct param_list *params = method->params;
  102.     struct param *p;
  103.     struct keyword_param *k;
  104.  
  105.     if (parent) {
  106.     method->parent = parent;
  107.     method->next = parent->kids;
  108.     parent->kids = method;
  109.     }
  110.  
  111.     analize_expr(method->specializers, lexenv);
  112.     if (method->rettypes) {
  113.     analize_expr(method->rettypes->req_types_list, lexenv);
  114.     if (method->rettypes->rest_temp_varref)
  115.         analize_expr(method->rettypes->rest_temp_varref, lexenv);
  116.     }
  117.  
  118.     for (p = params->required_params; p != NULL; p = p->next)
  119.     bindings = make_binding(p->id, p->type_temp, TRUE, offset++, method,
  120.                 bindings);
  121.     if (params->rest_param)
  122.     bindings = make_binding(params->rest_param, NULL, TRUE, offset++,
  123.                 method, bindings);
  124.     for (k = params->keyword_params; k != NULL; k = k->next)
  125.     bindings = make_binding(k->id, NULL, TRUE, offset++, method, bindings);
  126.     if (params->next_param)
  127.     bindings = make_binding(params->next_param, NULL, TRUE, offset,
  128.                 method, bindings);
  129.  
  130.     method->nargs = offset+1;
  131.     method->lexenv = make_lexenv(method, bindings, 0);
  132.  
  133.     analize_body(method->body, method->lexenv);
  134. }
  135.  
  136.  
  137. /* Expression analysis */
  138.  
  139.  
  140. static void analize_varref_expr(struct varref_expr *expr,
  141.                 struct lexenv *lexenv)
  142. {
  143.     struct binding *binding
  144.     = find_and_maybe_close_over(expr->var, lexenv, &expr->over);
  145.  
  146.     expr->home = lexenv->method;
  147.     expr->binding = binding;
  148.  
  149.     if (binding == NULL && expr->var->symbol == sym_NextMethod)
  150.     warn(expr->var->line, "next-method not bound -- Mindy requires #next");
  151. }
  152.  
  153. static void analize_literal_expr(struct literal_expr *expr,
  154.                  struct lexenv *lexenv)
  155. {
  156.     /* Nothing to do. */
  157. }
  158.  
  159. static void analize_call_expr(struct call_expr *expr,
  160.                   struct lexenv *lexenv)
  161. {
  162.     struct argument *arg;
  163.  
  164.     analize_expr(expr->func, lexenv);
  165.     for (arg = expr->args; arg != NULL; arg = arg->next)
  166.     analize_expr(arg->expr, lexenv);
  167. }
  168.  
  169. static void analize_method_expr(struct method_expr *expr,
  170.                 struct lexenv *lexenv)
  171. {
  172.     analize_method(expr->method, lexenv);
  173. }
  174.  
  175. static void analize_dot_expr(struct dot_expr *expr,
  176.                  struct lexenv *lexenv)
  177. {
  178.     analize_expr(expr->arg, lexenv);
  179.     analize_expr(expr->func, lexenv);
  180. }
  181.  
  182. static void analize_body_expr(struct body_expr *expr,
  183.                   struct lexenv *lexenv)
  184. {
  185.     analize_body(expr->body, lexenv);
  186. }
  187.  
  188. static void analize_block_expr(struct block_expr *expr,
  189.                    struct lexenv *lexenv)
  190. {
  191.     lose("block expression made it though expand?");
  192. }
  193.  
  194. static void analize_case_expr(struct case_expr *expr,
  195.                   struct lexenv *lexenv)
  196. {
  197.     lose("case expression made it though expand?");
  198. }
  199.  
  200. static void analize_if_expr(struct if_expr *expr,
  201.                 struct lexenv *lexenv)
  202. {
  203.     analize_expr(expr->cond, lexenv);
  204.     analize_body(expr->consequent, lexenv);
  205.     analize_body(expr->alternate, lexenv);
  206. }
  207.  
  208. static void analize_for_expr(struct for_expr *expr,
  209.                  struct lexenv *lexenv)
  210. {
  211.     lose("for expression made it though expand?");
  212. }
  213.  
  214. static void analize_select_expr(struct select_expr *expr,
  215.                 struct lexenv *lexenv)
  216. {
  217.     lose("select expression made it though expand?");
  218. }
  219.  
  220. static void analize_varset_expr(struct varset_expr *expr,
  221.                 struct lexenv *lexenv)
  222. {
  223.     struct binding *binding
  224.     = find_and_maybe_close_over(expr->var, lexenv, &expr->over);
  225.  
  226.     if (binding) {
  227.     binding->set = TRUE;
  228.     if (binding->type) {
  229.         struct expr *type = make_varref(id(binding->type));
  230.         expr->type = (struct varref_expr *)type;
  231.         analize_expr(type, lexenv);
  232.     }
  233.     }
  234.  
  235.     expr->home = lexenv->method;
  236.     expr->binding = binding;
  237.  
  238.     analize_expr(expr->value, lexenv);
  239. }
  240.  
  241. static void analize_binop_series_expr(struct binop_series_expr *expr,
  242.                       struct lexenv *lexenv)
  243. {
  244.     lose("binop_series expression made it though expand?");
  245. }
  246.  
  247. static void analize_loop_expr(struct loop_expr *expr,
  248.                   struct lexenv *lexenv)
  249. {
  250.     analize_body(expr->body, lexenv);
  251. }
  252.  
  253. static void analize_repeat_expr(struct repeat_expr *expr,
  254.                 struct lexenv *lexenv)
  255. {
  256.     /* Nothing to do. */
  257. }
  258.  
  259. static void analize_error_expr(struct expr *expr, struct lexenv *lexenv)
  260. {
  261.     lose("Called environment on a parse tree with errors?");
  262. }
  263.  
  264. static void (*ExprAnalizers[])() = {
  265.     analize_varref_expr, analize_literal_expr, analize_call_expr,
  266.     analize_method_expr, analize_dot_expr, analize_body_expr,
  267.     analize_block_expr, analize_case_expr, analize_if_expr, analize_for_expr,
  268.     analize_select_expr, analize_varset_expr, analize_binop_series_expr,
  269.     analize_loop_expr, analize_repeat_expr, analize_error_expr
  270. };
  271.  
  272. static void analize_expr(struct expr *expr, struct lexenv *lexenv)
  273. {
  274.     if (expr->analized)
  275.     lose("Analizing an expression we have already analized?");
  276.     else {
  277.     expr->analized = TRUE;
  278.     (*ExprAnalizers[(int)expr->kind])(expr, lexenv);
  279.     }
  280. }
  281.  
  282.  
  283.  
  284. /* Constituent analysis */
  285.  
  286. static void analize_defconst_constituent(struct defconst_constituent *c,
  287.                      struct lexenv *lexenv)
  288. {
  289.     analize_method(c->tlf, lexenv);
  290. }
  291.  
  292. static void analize_defvar_constituent(struct defvar_constituent *c,
  293.                        struct lexenv *lexenv)
  294. {
  295.     analize_method(c->tlf, lexenv);
  296. }
  297.  
  298. static void analize_defmethod_constituent(struct defmethod_constituent *c,
  299.                       struct lexenv *lexenv)
  300. {
  301.     analize_method(c->tlf, lexenv);
  302. }
  303.  
  304. static void analize_defgeneric_constituent(struct defgeneric_constituent *c,
  305.                        struct lexenv *lexenv)
  306. {
  307.     analize_method(c->tlf, lexenv);
  308. }
  309.  
  310. static void analize_defclass_constituent(struct defclass_constituent *c,
  311.                      struct lexenv *lexenv)
  312. {
  313.     analize_method(c->tlf1, lexenv);
  314.     analize_method(c->tlf2, lexenv);
  315. }
  316.  
  317. static void analize_expr_constituent(struct expr_constituent *c,
  318.                      struct lexenv *lexenv)
  319. {
  320.     analize_expr(c->expr, lexenv);
  321. }
  322.  
  323. static void analize_local_constituent(struct local_constituent *c,
  324.                       struct lexenv *lexenv)
  325. {
  326.     struct method *home = lexenv->method;
  327.     struct binding *bindings = NULL;
  328.     struct binding **prev = &bindings;
  329.     struct method *method;
  330.     int offset = lexenv->depth;
  331.  
  332.     c->offset = offset;
  333.  
  334.     for (method = c->methods; method != NULL; method = method->next_local) {
  335.     struct binding *new = make_binding(method->name, NULL, FALSE, offset++,
  336.                        home, NULL);
  337.     new->function = TRUE;
  338.     new->set = TRUE;
  339.     *prev = new;
  340.     prev = &new->next;
  341.     }
  342.  
  343.     if (offset > home->frame_size)
  344.     home->frame_size = offset;
  345.  
  346.     *prev = lexenv->bindings;
  347.     c->lexenv = make_lexenv(home, bindings, offset);
  348.  
  349.     for (method = c->methods; method != NULL; method = method->next_local)
  350.     analize_method(method, c->lexenv);
  351.  
  352.     analize_body(c->body, c->lexenv);
  353. }
  354.  
  355. static void analize_handler_constituent(struct handler_constituent *c,
  356.                     struct lexenv *lexenv)
  357. {
  358.     analize_body(c->body, lexenv);
  359. }
  360.  
  361. static void analize_let_constituent(struct let_constituent *let,
  362.                     struct lexenv *lexenv)
  363. {
  364.     struct method *home = lexenv->method;
  365.     struct binding *bindings = lexenv->bindings;
  366.     int offset = lexenv->depth;
  367.     int req = 0;
  368.     struct param_list *params = let->bindings->params;
  369.     struct param *param;
  370.  
  371.     analize_expr(let->bindings->expr, lexenv);
  372.  
  373.     let->inside = bindings;
  374.     let->offset = offset;
  375.  
  376.     for (param = params->required_params; param != NULL; param = param->next) {
  377.     bindings = make_binding(param->id, param->type_temp, FALSE, offset++,
  378.                 home, bindings);
  379.     req++;
  380.     }
  381.     let->required = req;
  382.  
  383.     if (params->rest_param)
  384.     bindings = make_binding(params->rest_param, NULL, FALSE, offset++,
  385.                 home, bindings);
  386.  
  387.     let->lexenv = make_lexenv(home, bindings, offset);
  388.  
  389.     if (offset > home->frame_size)
  390.     home->frame_size = offset;
  391.  
  392.     analize_body(let->body, let->lexenv);
  393. }
  394.  
  395. static void analize_tlf_constituent(struct tlf_constituent *c,
  396.                     struct lexenv *lexenv)
  397. {
  398.     analize_method(c->form, lexenv);
  399. }
  400.  
  401. static void analize_error_constituent(struct constituent *c,
  402.                       struct lexenv *lexenv)
  403. {
  404.     lose("Called environment on a parse tree with errors?");
  405. }
  406.  
  407. static void analize_defmodule_constituent(struct constituent *c,
  408.                       struct lexenv *lexenv)
  409. {
  410.     /* Do nothing. */
  411. }
  412.  
  413. static void analize_deflibrary_constituent(struct constituent *c,
  414.                        struct lexenv *lexenv)
  415. {
  416.     /* Do nothing. */
  417. }
  418.  
  419. static void (*AnalizeConstituents[])() = {
  420.     analize_defconst_constituent, analize_defvar_constituent,
  421.     analize_defmethod_constituent, analize_defgeneric_constituent,
  422.     analize_defclass_constituent, analize_expr_constituent,
  423.     analize_local_constituent, analize_handler_constituent,
  424.     analize_let_constituent, analize_tlf_constituent,
  425.     analize_error_constituent, analize_defmodule_constituent,
  426.     analize_deflibrary_constituent
  427. };
  428.  
  429. static void analize_body(struct body *body, struct lexenv *lexenv)
  430. {
  431.     struct constituent *c;
  432.  
  433.     for (c = body->head; c != NULL; c = c->next)
  434.     (*AnalizeConstituents[(int)c->kind])(c, lexenv);
  435. }
  436.  
  437. void environment_analysis(struct body *body)
  438. {
  439.     struct lexenv *lexenv = make_lexenv(NULL, NULL, 0);
  440.  
  441.     analize_body(body, lexenv);
  442.  
  443.     free(lexenv);
  444. }
  445.